package root.loan;

import java.util.Calendar;
import java.util.GregorianCalendar;

import root.item.Item;
import root.user.User;
import exceptions.HasAlreadyDoneException;
import exceptions.LoanHasAlreadyBeenApprovedException;
import exceptions.PermissionDeniedException;

/**
 * 
 * Classe Contexto para o padrao State
 *
 */
public class Borrow {
	private User interested;
	private int days;
	private State status;
	private Item item;
	private GregorianCalendar dayOfAprove;
	private String id;
	
	public Borrow(String id, User interested, Item item, int days){
		this.id = id;
		this.item = item;
		this.interested = interested;
		this.days = days;
		
		status = new Request();
	}
	
	/**
	 * muda o estado do do emprestimo
	 * @param state
	 */
	public void mudaEstado(State state){
		this.status = state;
	}
	
	/**
	 * requisita devolucao de item emprestado
	 * @throws HasAlreadyDoneException
	 */
	public void requestDevolution() throws HasAlreadyDoneException ,PermissionDeniedException{
		status.requestDevolution(this);
		
	}

	/**
	 * cancela o emprestimo do item
	 * @throws HasAlreadyDoneException
	 */
	public void cancel() throws HasAlreadyDoneException ,PermissionDeniedException{
		status.cancel(this);
		
	}
	
	/**
	 * {@code} se o emprestimo foi concluido ( o dono do item confirmou devolucao do item )
	 * @return
	 */
	public boolean isComplete(){
		return status.isComplete();
	}

	/**
	 * muda o estado de emprestimo do item para um estado em que o dono confirmou devolucao
	 * @throws HasAlreadyDoneException
	 */
	public void complete() throws HasAlreadyDoneException ,PermissionDeniedException{
		status.complete(this);
		
	}

	/**
	 * muda estado de emprestimo para um em que o beneficiado devolveu o item para o dono
	 * @throws HasAlreadyDoneException
	 */
	public void returnItem() throws HasAlreadyDoneException ,PermissionDeniedException{
		status.returnItem(this);
		
	}

	/**
	 * muda o estado de emprestimo para um em que o dono aprovou a requisicao
	 * @param dayOfAprove
	 * @throws LoanHasAlreadyBeenApprovedException
	 */
	public void aproveBorrow(GregorianCalendar dayOfAprove) throws LoanHasAlreadyBeenApprovedException ,PermissionDeniedException{
		this.dayOfAprove = ((GregorianCalendar) dayOfAprove.clone());
		status.aproveBorrow(this);
	}
	
	/**
	 * 
	 * @return {@code} se o estado do emrestimo for de requisicao
	 */
	public boolean isRequest(){
		return status.isRequest();
	}
	
	public GregorianCalendar expecteDayOfDevolution(){
		GregorianCalendar expect = ((GregorianCalendar) dayOfAprove.clone());
		expect.add(Calendar.DATE, days);
		return expect;
	}

	public User getInterested() {
		return interested;
	}
	
	public String getDescricao(){
		return status.getDescricao();
	}
	
	public void setInterested(User interested) {
		this.interested = interested;
	}

	public int getDays() {
		return days;
	}

	public void setDays(int days) {
		this.days = days;
	}

	public State getStatus() {
		return status;
	}

	public void setStatus(State status) {
		this.status = status;
	}

	public Item getItem() {
		return item;
	}


	public GregorianCalendar getDayOfAprove() {
		return dayOfAprove;
	}

	public void setDayOfAprove(GregorianCalendar dayOfAprove) {
		this.dayOfAprove = (GregorianCalendar) dayOfAprove.clone();
	}
	
	public boolean equals(Object o){
		if(! (o instanceof Borrow)) return false;
		return id.equals(((Borrow)o).id);
	}
	
	public int hashCode(){
		return id.hashCode();
	}
	
	public String getId(){
		return id;
	}
}